<?php

defined("IN_CART") or die;

class CModel {
	
	protected $db		= null;
	
	protected $name		= '';

	protected $tbname	= '';
	
	protected $tbprefix = '';

	protected $error	= '';

	protected $data		= array();

	protected $options	= array();

	protected $pk	    = '';

	public function __construct($name = '') {
		$this->_initialize();
		
		$this->name = $name ? $name : $this->getModelName();
		
		$this->db = $this->getDB();
	}
	
	public function getDB() {
		if($this->db) return $this->db;

		static $_db;
		$options = C('db');
		$this->tbprefix = isset($options['tbprefix']) ? $options['tbprefix'] :'';
		if(!$_db) $_db = CDb::getInstance($options);
		return $_db;
	}

	protected function _initialize() {
		
	}
	
	public function __set($name,$value) {
		$this->data[$name] = $value;
 	}

	public function __get($name) {
		return isset($this->data[$name]) ? $this->data[$name] : null;
	}

	public function __isset($name) {
		return isset($this->data[$name]);
	}

	public function __unset($name) {
		if(isset($this->data[$name])) unset($this->data[$name]);
	}
	
	public function replace($data = array(),$options = array()) {
		return $this->add($data,$options,true);
	}

	public function replaceMulti($dataList = array(),$options = array()) {
		return $this->addMulti($dataList,$options,true);
	}

	public function add($data = array(),$options = array(),$replace = false) {
		$data = $this->parseData($data);
		if(!$data) return false;

		$options = $this->parseOptions($options);
		return $this->db->insert($data,$options,$replace);
	}
	
	//返回增加的行数或影响的行数
	public function addMulti($dataList = array() ,$options = array() , $replace = false) {
		if(!$dataList || !is_array($dataList)) {
			$this->error = L("NO_DATA");
			return false;
		}
		
		$options = $this->parseOptions($options);
		return $this->db->insertMulti($dataList,$options,$replace);
	}

	public function update($data = array(),$where = array()) {
		$data = $this->parseData($data);
		if(!$data) return false;
		
		$options = array();
		$where && $options['where']    = $where;
		$options = $this->parseOptions($options);
		$nums = $this->db->update($data,$options);
		return $nums;
	}
	
	//查询多条数据
	public function select($keyid = '',$type = 'rows',$options = array()) {
		$options = $this->parseOptions($options);
		return $this->db->select($options,$type,$keyid);
	}
	
	public function delete($where = array()) {
		$options = array();
		$where && $options['where']    = $where;
		$options	= $this->parseOptions($options,$where);
		return $this->db->delete($options);
	}
	
	protected function parseData($data = array()) {
		if(is_array($data)) $data = array_merge($this->data,$data);
		$this->data = array();
		if(!$data) {
			$this->error = L("NO_DATA");
			return false;
		}
		return $data;
	}

	protected function parseOptions($options = array()) {
		if(is_array($options)) $options = array_merge($this->options,$options);
		$this->options = array();
		
		if(isset($options['where']) && $options['where']) {
			$where = $options['where'];
			if(is_numeric($where)) {//如果为数字型，
				 $pk		= $this->getPK();
				 $where		= array($pk=>$where);
			} else if(is_string($where)) {//如果为字符型，有两类，1，"1,2,3"，2，"catid='1'"; 
				if(preg_match("/^[a-z0-9,]+$/i",$where)) { //形如，"1,2,3";
					$pk		= $this->getPK();
					$where	= array($pk=>strpos($where,",") ? "in ($where)" : $where);
				}
			}
			
			$options['where'] = $where;
		}


		empty($options['table']) && $options['table'] = $this->getTableName();
		return $options;
	}

	public function getModelName() {
		 if(empty($this->name)) {
			 $this->name =   substr(get_class($this),0,-5);
         }
         return $this->name;
	}

	public function getTableName() {
		if(!empty($this->tbname)) return $this->tbname;

		$this->tbname = $this->tbprefix.strtolower($this->name);
		
		return $this->tbname;
	}

	public function getError() {
		if($this->error) {
			return $this->error;
		}
		return $this->db->getError();
	}
	
	//call方法实现连贯操作
	public function __call($method,$args) {
		$method = strtolower($method);
		if(in_array($method,array("distinct","fields","where","limit","order","group","having"),true)) {
			$this->options[$method] = isset($args[0]) ? $args[0] : '';
			return $this;
		} else if("from" === $method) {
			$this->options['table'] = $this->tbprefix . strtolower($args[0]);
			return $this;
		} else if("join" === $method) {
			if(is_array($args[0]) && isset($args[0]['table']) ) {
				$args[0]['table'] = $this->tbprefix.strtolower($args[0]['table']);
			} else if( count($args) == 3  ) {
				$args[0] = array(
					"type"	=>	$args[0],
					"table"	=>	$this->tbprefix.strtolower($args[1]),
					"on"	=>	$args[2]
				);			
			}
			$this->options['join'] = $args[0];
			return $this;
		} else if(in_array($method,array("data"))) {//设置data
			$this->$method = $args[0];
			return $this;
		} else if(preg_match("/^select(val|row|col)$/",$method,$matches)) {//查询一行，一列，一个元素
			return $this->select('',$matches[1],isset($args[0]) ? $args[0] : '');
		} else if(in_array($method,array("sum","count","max","min","avg"))) {
			$field = isset($args[0]) ? $args[0] : '*';
			if(strpos($field,".")) {
				list($pre,$field) = explode(".",$field);
				$field = $pre . '.' . $this->db->quoteKey($field);
			} else {
				$field = $this->db->quoteKey($field);
			}
			$this->options['fields'] = strtoupper($method) . "($field)";
			return $this->select('','val');
		}
		$this->error = L("NO_METHOD");
	}

	//获取主键，如果使用delete数字，
	//如果表的主键不是表明+id,会报错，在相应的model中指定pk
	public function getPK() {
		if(empty($this->pk)) {
			$this->pk = strtolower($this->name) . 'id';
		}
		return $this->pk;
	}

	public function sql() {
		return $this->db->sql();
	}

	public function getLastId() {
		return $this->db->getLastId();
	}

}